/**
 * The MIT License	
 * 
 * Copyright (c) 2009 Ghost Interactive
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 * ghostinteractive@gmail.com
 * http://ghostinteractive.net/blog
 * @author Jeremy brown
 */
package net.ghostinteractive.overlays
{
	import caurina.transitions.properties.SoundShortcuts;
	
	import flash.events.EventDispatcher;
	import flash.geom.Point;
	
	import org.openzoom.flash.components.MultiScaleImage;
	import org.openzoom.flash.descriptors.IMultiScaleImageDescriptor;
	import org.openzoom.flash.events.ViewportEvent;
	import org.openzoom.flash.viewport.IViewport;
	
	public class AudioLayer extends EventDispatcher
	{
		protected var _audiospots	:Array;
		protected var _image		:MultiScaleImage;
		
		/**
	 	 * Constructor
	 	 * AudioLayer provides a means of adding audio to an OpenZoom MultiScaleImage
	 	 * This class listens to an instance of the MultiScaleImage for transform update events
	 	 * and passes the current coordinate of the image aligned with the center of the viewport
	 	 * to each AudioSpot
	 	 * 
	 	 * @param MultiScaleImage to sync this layer with
	 	 */
		public function AudioLayer( image:MultiScaleImage = null )
		{
			_audiospots = [];
			SoundShortcuts.init();
			if( image ) { multiScaleImage = image; }
		}
		
		// -----------------------------------------------------
		//
		//	PUBLIC
		//	
		// -----------------------------------------------------
		
		/**
		 * Setting this param essentially syncs the AudioLayer to a MultiScaleImage instance 
		 * Calls purge() method to remove listeners to previous MultiScaleImage and any AudioSpots
		 * previously in use
		 * 
		 * @param _image MultiScaleImage instance for HotspotLayer to sync with
		 */
		public function set multiScaleImage( image:MultiScaleImage ):void
		{
			if( _image ) { purge() };
			
			_image 	= image;
	
			addListeners();
		}
		
		/**
		 * Removes all audiospots and listeners, calling this function will render
		 * the audio layer useless until the multiScaleImage property is once again set
		 */
		public function purge():void
		{
			removeAllAudioSpots();
			removeListeners();
		}
		
		/**
		 * Add audio item to layer
		 */
		public function addAudioSpot( audiospot:AudioSpot ):void { _audiospots.push( audiospot ); }
		
		/**
		 * Calls destroy on each audiospot and removes it from the array
		 * This will completely remove the audiospot 
		 */ 
		public function removeAllAudioSpots():void 
		{
			for each ( var audiospot:AudioSpot in _audiospots ) 
			{
				audiospot.destroy();
			}
			_audiospots.splice( 0 );
		}
		
		/**
		 * Use this method to retrieve an AudioSpot object
		 * @param url A url used to find an AudioSpot object
		 * @return AudioSpot An AudioSpot object with a url matching that of the search url
		 * 					 returns null if no match is found
		 */
		public function getAudioSpotByURL( url:String ):AudioSpot
		{
			for each ( var audiospot:AudioSpot in _audiospots ) 
			{
				if( audiospot.audioURL == url ) {
					return audiospot;
				}
			}
			return null;
		}
		
		// -----------------------------------------------------
		//
		//	PROTECTED
		//	
		// -----------------------------------------------------
		
		// -----------------------------------------------
		//	Event Handlers
		// -----------------------------------------------
		
		/**
		 * Calculate the point in the image relative to the original image size that 
		 * is aligned with the center of the MultiScaleImage
		 * Iterate through the array of audiospots 
		 * Call update on each audiospot's gate property and pass in the center and image's zoom level
		 */
		protected function onTransformUpdate( event:ViewportEvent ):void
		{
			var descriptor:IMultiScaleImageDescriptor = IMultiScaleImageDescriptor( _image.source );
			if( descriptor )
			{
				var viewport:IViewport = _image.viewport;
				
				var centerY:Number = ( viewport.y + ( viewport.height / 2 ) ) * descriptor.height;
				var centerX:Number = ( viewport.x + ( viewport.width / 2 ) ) * descriptor.width;
				var center:Point = new Point( centerX, centerY );
				
				var audiospot:AudioSpot;
				var gate:ProximityGate;
				var zoom:Number = _image.zoom;
				
				for each( audiospot in _audiospots ) 
				{
					gate 	= audiospot.gate;
					gate.update( center, _image.zoom );
				}
			}
		}
		
		/**
		 * Adds event listeners
		 */
		protected function addListeners():void
		{
			_image.viewport.addEventListener( ViewportEvent.TRANSFORM_UPDATE, onTransformUpdate );
		}
		
		/**
		 * Removes event listeners
		 */
		protected function removeListeners():void
		{
			_image.viewport.removeEventListener( ViewportEvent.TRANSFORM_UPDATE, onTransformUpdate );
		}
		
	}
}